/*
 * @Author: wuqingchun
 * @Date: 2024-04-22 11:27:01
 * @Description: 类模板的定义
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-05-07 10:05:34
 */
#ifndef __TEMPLATE_CLASS_H__
#define __TEMPLATE_CLASS_H__

#include <iostream>
#include <thread>
#include <functional>

enum class WorkMode
{
    WMODE_CONSUMER,
    WMODE_PRODUCER,
    WMODE_CONSUMER_PRODUCER
};

template <WorkMode enWorkMode = WorkMode::WMODE_CONSUMER>
class WorkerThread
{
private:
    std::thread m_objThread;
    volatile bool m_bRunning {false};
    std::vector<std::thread> m_vecThreads;
public:

    ~WorkerThread()
    {
        m_bRunning = false;

        for (auto& refThread : m_vecThreads)
        {
            if (refThread.joinable())
            {
                refThread.join();
            }
        }
    }

    template <int SLEEP_SECS=1>
    void Start()
    {
        m_bRunning = true;

        switch (enWorkMode)
        {
            case WorkMode::WMODE_CONSUMER:
            {
                m_vecThreads.push_back(std::thread(&WorkerThread::Consumer, this));
                break;
            }
            case WorkMode::WMODE_PRODUCER:
            {
                m_vecThreads.push_back(std::thread(&WorkerThread::Producer, this));
                break;
            }
            case WorkMode::WMODE_CONSUMER_PRODUCER:
            default:
            {
                m_vecThreads.push_back(std::thread(&WorkerThread::Consumer, this));
                m_vecThreads.push_back(std::thread(&WorkerThread::Producer, this));
                break;
            }
        }

        std::this_thread::sleep_for(std::chrono::seconds(SLEEP_SECS));
    }

    // 类成员函数指针类型作为模板参数，本质上也是一个类型参数模板
    template <void (WorkerThread::*StartThread)(), int SLEEP_SECS=1>
    void Start()
    {
        m_bRunning = true;
        (this->*StartThread)();
        std::this_thread::sleep_for(std::chrono::seconds(SLEEP_SECS));
    }

    void StartConsumer()
    {
        m_vecThreads.push_back(std::thread(&WorkerThread::Consumer, this));
    }

    void StartProducer()
    {
        m_vecThreads.push_back(std::thread(&WorkerThread::Producer, this));
    }
    
private:
    void Consumer()
    {
        while(m_bRunning)
        {
            std::cout << "I am a consumer" << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }

    void Producer()
    {
        while(m_bRunning)
        {
            std::cout << "I am a producer" << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
};

template <typename T, typename U>
struct MyAdder
{
    MyAdder()
    {
        std::cout << "primary template" << std::endl;
    }
};

template <>
struct MyAdder<int, double>
{
    MyAdder()
    {
        std::cout << "full specialization" << std::endl;
    }
};

template <typename T>
struct MyAdder<T, double>
{
    MyAdder()
    {
        std::cout << "partial specialization" << std::endl;
    }
};

#endif //__TEMPLATE_CLASS_H__